package com.yaoxun.console.service;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import com.yaoxun.console.constant.CacheConstant;
import com.yaoxun.console.context.SubjectContextHolder;
import com.yaoxun.console.exception.ValidatorException;
import com.yaoxun.console.xo.dto.LoginSession;
import com.yaoxun.console.xo.entity.LoginUser;
import com.yaoxun.console.xo.req.PasswrodUpdateReq;
import com.yaoxun.console.xo.req.UserDeleteReq;
import com.yaoxun.console.xo.req.UserEditReq;
import com.yaoxun.console.xo.resp.LoginUserResp;
import com.yaoxun.console.xo.resp.PageInfo;

@Service
public class UserService {

	@Autowired
	private StringRedisTemplate stringRedisTemplate;
	
	@Autowired
	private JsonService jsonService;
	
	private void checkExistLoginName(String loginName) {
		Boolean exist = stringRedisTemplate.opsForHash().hasKey(CacheConstant.LOGIN_USERS, loginName);
		if(exist) {
			throw new ValidatorException("登录账号【"+loginName+"】已经存在");
		}
	}
	
	private void checkNotExistLoginName(String loginName) {
		Boolean exist = stringRedisTemplate.opsForHash().hasKey(CacheConstant.LOGIN_USERS, loginName);
		if(!exist) {
			throw new ValidatorException("登录账号【"+loginName+"】不存在");
		}
	}
	
	
	public LoginUser get(String loginName) {
		String json = (String) stringRedisTemplate.opsForHash().get(CacheConstant.LOGIN_USERS, loginName);
		if(json == null) {
			return null;
		}
		
		return jsonService.parse(json, LoginUser.class);
	}
	
	
	public void add(UserEditReq req) {
		
		checkExistLoginName(req.getLoginName());
		
		LoginUser user = new LoginUser();
		user.setLoginName(req.getLoginName())
			.setPassword(req.getPassword())
			.setCreateTime(new Date());
		
		String json = jsonService.toJsonString(user);
		
		stringRedisTemplate.opsForHash().put(CacheConstant.LOGIN_USERS, req.getLoginName(), json);
		
	}

	public void update(UserEditReq req) {
		
		String json = (String) stringRedisTemplate.opsForHash().get(CacheConstant.LOGIN_USERS, req.getLoginName());
		
		if(json == null) {
			throw new ValidatorException("登录账号【"+req.getLoginName()+"】不存在");
		}
		
		LoginUser user = jsonService.parse(json, LoginUser.class);
		
		user.setPassword(req.getPassword());
		
		json = jsonService.toJsonString(user);
		
		stringRedisTemplate.opsForHash().put(CacheConstant.LOGIN_USERS, req.getLoginName(), json);
		
	}
	
	public PageInfo<LoginUserResp> list() {
		
		PageInfo<LoginUserResp> pageInfo = new PageInfo<>();
		
		List<Object> values = stringRedisTemplate.opsForHash().values(CacheConstant.LOGIN_USERS);
		
		if(CollectionUtils.isEmpty(values)) {
			return pageInfo;
		}
		
		List<LoginUserResp> records = new ArrayList<>();
		
		values.forEach(e -> {
			
			LoginUserResp user = jsonService.parse(e.toString(), LoginUserResp.class);
			
			records.add(user);
			
		});
		
		List<LoginUserResp> newRecords = records.stream()
					.sorted(Comparator.comparing(LoginUserResp::getCreateTime).reversed())
					.collect(Collectors.toList());
		
		pageInfo.setRecords(newRecords);
		
		return pageInfo;
	}

	public void delete(UserDeleteReq req) {
		
		checkNotExistLoginName(req.getLoginName());
		
		if("admin".equals(req.getLoginName())) {
			throw new ValidatorException("账号【admin】无法删除");
		}
		
		stringRedisTemplate.opsForHash().delete(CacheConstant.LOGIN_USERS, req.getLoginName());
		
	}

	public void updatePassword(PasswrodUpdateReq req) {
		
		LoginSession session = SubjectContextHolder.getContext();
		
		String json = (String) stringRedisTemplate.opsForHash().get(CacheConstant.LOGIN_USERS, session.getLoginName());
		
		LoginUser user = jsonService.parse(json, LoginUser.class);
		
		user.setPassword(req.getPassword());
		
		json = jsonService.toJsonString(user);
		
		stringRedisTemplate.opsForHash().put(CacheConstant.LOGIN_USERS, user.getLoginName(), json);
		
	}

	
}
